﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Datamining.Models;

namespace Datamining.Program
{
    public class Program
    {
        private static Pearson pearson = new Pearson();

        public static SortedDictionary<int, UserPreferences> userRatingDictionary = new SortedDictionary<int, UserPreferences>();
        public static SortedDictionary<int, Items> itemDictionary = new SortedDictionary<int, Items>();
        public static SortedDictionary<int, Genres> genreDictionary = new SortedDictionary<int, Genres>();
        public static Dictionary<int, Dictionary<int, double>> slopeOneDifference;
        
        public static void Main(string[] args)
        {
            ImportData id = new ImportData();
            //id.ReadTestData();
            
            id.ReadData();
            id.ReadItem();
            id.ReadGenre();

            SlopeOne slope = new SlopeOne();
            slopeOnePreProcessAndPrintTimes(slope);
            showSlopeOneInput(slope);

            //pearson.PrintFutureRecommendation(6);
            //pearson.PrintArticleSimalarityByUserId(186);
            
            Console.WriteLine(" ");
            Console.WriteLine("Einde programma klik om af te sluiten.");

            Console.ReadLine();
        }

        private static void showSlopeOneInput(SlopeOne slope)
        {
            Console.WriteLine("");
            int choisenNumber = -111;
            while (choisenNumber != 0)
            {
                Console.WriteLine("");
                Console.WriteLine("-------------------------------------------------------");
                Console.WriteLine("Slope One prediction == 1");
                Console.WriteLine("update User rating & prediction == 2");
                Console.WriteLine("Stoppen == 0");
                Console.WriteLine("Maak een keuze!");
                int entered = -111;
                bool isCorrectFirst = int.TryParse(Console.ReadLine(), out entered);
                if (entered == 0 && isCorrectFirst)
                {
                    choisenNumber = entered;
                    break;
                }
                else if(entered == 1 && isCorrectFirst)
                {
                    showGUIPrediction(slope);
                }
                else if (entered == 2 && isCorrectFirst)
                {
                    showGUIUpdateUserRating(slope);
                }
            }
        }

        private static void showGUIUpdateUserRating(SlopeOne slope)
        {
            Console.WriteLine("");
            int userid = 0;
            Console.WriteLine("Voer een userid (1 t/m " + userRatingDictionary.Count + ") in waarvoor je rating wilt updaten:");
            bool isCorrect = int.TryParse(Console.ReadLine(), out userid);

            if (userRatingDictionary.ContainsKey(userid) && isCorrect)
            {
                int itemid = 0;
                Console.WriteLine("Voer een itemid (1 t/m " + itemDictionary.Count + ") in waarvoor je rating wilt updaten:");
                bool isCorrectItemId = int.TryParse(Console.ReadLine(), out itemid);
                if (itemDictionary.ContainsKey(itemid) && isCorrectItemId)
                {
                    double rating = 0;
                    Console.WriteLine("Voer een rating (1 t/m 5) in:");
                    bool isCorrectRating = double.TryParse(Console.ReadLine(), out rating);
                    if (isCorrectItemId)
                    {
                        Console.WriteLine("");
                        Console.WriteLine("Updaten user rating gegevens!");

                        userRatingDictionary[userid].setItemIDRating(itemid, rating);
                        slope.updateSlopeOneRating(itemid);

                        Console.WriteLine("Klaar met updaten user rating gegevens");
                    }
                    else
                    {
                        Console.WriteLine("Voer een correcte rating in!!!");
                        Console.WriteLine("");
                    }
                }
                else
                {
                    Console.WriteLine("Voer een correcte itemid in!!!");
                    Console.WriteLine("");
                }
            }
            else
            {
                Console.WriteLine("Voer een correcte userid in!!!");
                Console.WriteLine("");
            }
        }

        private static void showGUIPrediction(SlopeOne slope)
        {
            Console.WriteLine("");
            int userid = 0;
            Console.WriteLine("Voer een userid (1 t/m " + userRatingDictionary.Count + ") in waarvoor je de prediction wilt doen:");
            bool isCorrect = int.TryParse(Console.ReadLine(), out userid);

            if (userid > 0 && userid <= userRatingDictionary.Count && isCorrect)
            {
                Console.WriteLine("");
                DateTime startTime = DateTime.Now;
                Dictionary<int, double> result = slope.getPrediction(userid);
                Console.WriteLine("Start tijd prediction: " + startTime);
                Console.WriteLine("Eind tijd prediction: " + DateTime.Now);
                Console.WriteLine("");
                Console.WriteLine("De prediction voor user: " + userid + " heeft de volgende resultaten opgeleverd: ");
                foreach (KeyValuePair<int, double> item in result)
                {
                    Console.WriteLine("Item id: " + item.Key + " met prediction value: " + item.Value);
                }
            }
            else
            {
                Console.WriteLine("Voer een correcte userid in!!!");
                Console.WriteLine("");
            }
            
        }

        private static void slopeOnePreProcessAndPrintTimes(SlopeOne slope)
        {
            Console.WriteLine("Beginnen slope one preprocess.");

            DateTime startTime = DateTime.Now;

            slopeOneDifference = slope.preProcessSlopeOne();

            Console.WriteLine(" ");
            Console.WriteLine("Start tijd slopeOnePreProcess: " + startTime);
            Console.WriteLine("Eind tijd slopeOnePreProcess: " + DateTime.Now);
        }
    }
}
